home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 6 / CU Amiga Magazine's Super CD-ROM 06 (1996)(EMAP Images)(GB)(Track 1 of 4)[!][issue 1997-01].iso / cucd / prog / mui / modula / demo / class2.mod < prev    next >
Text File  |  1996-02-07  |  14KB  |  440 lines

  1. MODULE Class2 ;
  2.  
  3. (*
  4. ** Class2.mod by Olaf "Olf" Peters <olf@informatik.uni-bremen.de>
  5. **
  6. ** based upon Class2.c by Stefan Stuntz.
  7. **
  8. ** IMPORTANT: RangeChk mußt be switched off, otherwise you'll get an error
  9. ** when entering the Colorwheel-Page!
  10. **
  11. ** Updated Feb 07, 1996 by Olaf Peters
  12. ** - now uses MuiClassSupport for Classinitialisation
  13. **
  14. ** Updated Nov 27, 1995 by Olaf Peters:
  15. **  - does not use MUIOBSOLETE tags any longer
  16. **  - uses "the ideal input loop for an object oriented MUI application"
  17. **      (see MUI_Application.doc/MUIM_Application_NewInput)
  18. *)
  19.  
  20. (*$ RangeChk := FALSE *)
  21.  
  22. FROM SYSTEM     IMPORT  TAG, ADR, ADDRESS, LONGSET, CAST, SETREG, REG ;
  23. FROM AmigaLib   IMPORT  DoSuperMethodA ;
  24. FROM DosD       IMPORT  ctrlC ;
  25. FROM ExecL      IMPORT  Wait ;
  26.  
  27. IMPORT
  28.         R,
  29.         gd  : GraphicsD,
  30.         gl  : GraphicsL,
  31.         id  : IntuitionD,
  32.         il  : IntuitionL,
  33.         m   : MuiD,
  34.         mc  : MuiClasses,
  35.         mcs : MuiClassSupport,
  36.         ml  : MuiL,
  37.         mm  : MuiMacros,
  38.         ms  : MuiSupport,
  39.         ud  : UtilityD,
  40.         ul  : UtilityL ;
  41.  
  42. (***************************************************************************)
  43. (* Here is the beginning of our simple new class...                        *)
  44. (***************************************************************************)
  45.  
  46. (*
  47. ** This class is the same as within Class1.c except that it features
  48. ** a pen attribute.
  49. *)
  50.  
  51. TYPE
  52.   LongcardPtr = POINTER TO LONGCARD ;
  53.  
  54.   Data = RECORD
  55.            penspec   : m.mPenSpec ;
  56.            pen       : ADDRESS;
  57.            penchange : BOOLEAN ;
  58.          END (* RECORD *) ;
  59.  
  60. CONST
  61.   MyAttrPen = LONGCARD(8022H) ; (* tag value for the new attribute.            *)
  62.  
  63. (*/// "mNew(cl : id.IClassPtr; obj : id.ObjectPtr; msg : id.OpSetPtr) : ADDRESS" *)
  64.  
  65. PROCEDURE mNew(cl : id.IClassPtr; obj : id.ObjectPtr; msg : id.OpSetPtr) : ADDRESS ;
  66.  
  67. VAR
  68.   data  : POINTER TO Data ;
  69.   tag,
  70.   tags  : ud.TagItemPtr ;
  71.  
  72. BEGIN
  73.   obj := DoSuperMethodA(cl, obj, msg) ;
  74.   IF obj = NIL THEN RETURN NIL END ;
  75.  
  76.   data := mc.InstData(cl, obj) ;
  77.  
  78.   (* parse initial taglist *)
  79.  
  80.   tags := msg^.attrList ;
  81.   tag  := ul.NextTagItem(tags) ;
  82.   WHILE tag # NIL DO
  83.     CASE tag^.tag OF
  84.     | MyAttrPen : IF tag^.data # 0 THEN
  85.                     data^.penspec := CAST(m.mPenSpecPtr, tag^.data)^ ;
  86.                   END (* IF *) ;
  87.     ELSE
  88.     END (* CASE *) ;
  89.     tag := ul.NextTagItem(tags) ;
  90.   END (* WHILE *) ;
  91.  
  92.   RETURN obj ;
  93. END mNew ;
  94.  
  95. (*\\\*)
  96. (*/// "mDispose(cl : id.IClassPtr; obj : id.ObjectPtr; msg : ADDRESS) : ADDRESS" *)
  97.  
  98. PROCEDURE mDispose(cl : id.IClassPtr; obj : id.ObjectPtr; msg : ADDRESS) : ADDRESS ;
  99.  
  100. BEGIN
  101.   (* OM_NEW didnt allocates something, just do nothing here... *)
  102.   RETURN DoSuperMethodA(cl, obj, msg) ;
  103. END mDispose ;
  104.  
  105. (*\\\*)
  106.  
  107. (*
  108. ** OM_SET method, we need to see if someone changed the penspec attribute.
  109. *)
  110.  
  111. (*/// "mSet(cl : id.IClassPtr; obj : id.ObjectPtr; msg : id.OpSetPtr) : ADDRESS" *)
  112.  
  113. PROCEDURE mSet(cl : id.IClassPtr; obj : id.ObjectPtr; msg : id.OpSetPtr) : ADDRESS ;
  114.  
  115. VAR
  116.   data : POINTER TO Data ;
  117.   tag,
  118.   tags : ud.TagItemPtr ;
  119.  
  120. BEGIN
  121.   data := mc.InstData(cl, obj) ;
  122.  
  123.   tags := msg^.attrList ;
  124.   tag  := ul.NextTagItem(tags) ;
  125.   WHILE tag # NIL DO
  126.     CASE tag^.tag OF
  127.     | MyAttrPen : IF tag^.data # 0 THEN
  128.                     data^.penspec   := CAST(m.mPenSpecPtr, tag^.data)^ ;
  129.                     data^.penchange := TRUE ;
  130.                     IF ml.moRedraw(obj, CAST(LONGCARD, mc.MADFlagSet{mc.drawObject})) # NIL THEN END ;
  131.                   END (* IF *) ;
  132.     ELSE
  133.     END (* CASE *) ;
  134.     tag := ul.NextTagItem(tags) ;
  135.   END (* WHILE *) ;
  136.  
  137.   RETURN DoSuperMethodA(cl, obj, msg) ;
  138. END mSet ;
  139.  
  140. (*\\\*)
  141.  
  142. (*
  143. ** OM_GET method, see if someone wants to read the color.
  144. *)
  145.  
  146. (*/// "mGet(cl : id.IClassPtr; obj : id.ObjectPtr; msg : id.OpGetPtr) : ADDRES" *)
  147.  
  148. PROCEDURE mGet(cl : id.IClassPtr; obj : id.ObjectPtr; msg : id.OpGetPtr) : ADDRESS;
  149.  
  150. VAR
  151.   data  : POINTER TO Data ;
  152.   store : LongcardPtr ;
  153.  
  154. BEGIN
  155.   data := mc.InstData(cl, obj) ;
  156.   store := CAST(LongcardPtr, msg^.storage) ;
  157.  
  158.   CASE msg^.attrID OF
  159.   | MyAttrPen : store^ := ADR(data^.penspec) ;
  160.                 RETURN LONGCARD(TRUE) ;
  161.   ELSE
  162.     RETURN DoSuperMethodA(cl, obj, msg) ;
  163.   END (* CASE *) ;
  164. END mGet ;
  165.  
  166. (*\\\*)
  167. (*/// "mSetup(cl : id.IClassPtr; obj : id.ObjectPtr; msg : id.OpSetPtr) : ADDRES" *)
  168.  
  169. PROCEDURE mSetup(cl : id.IClassPtr; obj : id.ObjectPtr; msg : id.OpSetPtr) : ADDRESS;
  170.  
  171. VAR
  172.   data : POINTER TO Data ;
  173.   test : ADDRESS ;
  174.  
  175. BEGIN
  176.   data := mc.InstData(cl, obj) ;
  177.  
  178.   IF DoSuperMethodA(cl, obj, msg) = NIL THEN
  179.     RETURN LONGCARD(FALSE) ;
  180.   END (* IF *) ;
  181.  
  182.   test := mc.muiRenderInfo(obj) ;
  183.   data^.pen := ml.moObtainPen(mc.muiRenderInfo(obj), ADR(data^.penspec)) ;
  184.  
  185.   RETURN LONGCARD(TRUE) ;
  186. END mSetup ;     
  187.  
  188. (*\\\*)
  189. (*/// "mCleanup(cl : id.IClassPtr; obj : id.ObjectPtr; msg : id.OpSetPtr) : ADDRES" *)
  190.  
  191. PROCEDURE mCleanup(cl : id.IClassPtr; obj : id.ObjectPtr; msg : id.OpSetPtr) : ADDRESS;
  192.  
  193. VAR
  194.   data :POINTER TO Data ;
  195.  
  196. BEGIN
  197.   data := mc.InstData(cl, obj) ;
  198.   ml.moReleasePen(mc.muiRenderInfo(obj), data^.pen) ;
  199.   RETURN DoSuperMethodA(cl, obj, msg) ;
  200. END mCleanup ;
  201.  
  202. (*\\\*)
  203. (*/// "mAskMinMax(cl : id.IClassPtr; obj : id.ObjectPtr; msg : mc.mpAskMinMaxPtr) : ADDRES" *)
  204.  
  205. PROCEDURE mAskMinMax(cl : id.IClassPtr; obj : id.ObjectPtr; msg : mc.mpAskMinMaxPtr) : ADDRESS;
  206.  
  207. BEGIN
  208.   (*
  209.   ** let our superclass first fill in what it thinks about sizes.
  210.   ** this will e.g. add the size of frame and inner spacing.
  211.   *)
  212.  
  213.   IF DoSuperMethodA(cl, obj, msg) # NIL THEN END ;
  214.  
  215.   (*
  216.   ** now add the values specific to our object. note that we
  217.   ** indeed need to *add* these values, not just set them!
  218.   *)
  219.  
  220.   INC(msg^.MinMaxInfo^.MinWidth, 100) ;
  221.   INC(msg^.MinMaxInfo^.DefWidth, 120) ;
  222.   INC(msg^.MinMaxInfo^.MaxWidth, 500) ;
  223.  
  224.   INC(msg^.MinMaxInfo^.MinHeight, 40) ;
  225.   INC(msg^.MinMaxInfo^.DefHeight, 90) ;
  226.   INC(msg^.MinMaxInfo^.MaxHeight, 300) ;
  227.  
  228.   RETURN NIL ;
  229. END mAskMinMax ;
  230.  
  231. (*\\\*)
  232.  
  233. (*
  234. ** Draw method is called whenever MUI feels we should render
  235. ** our object. This usually happens after layout is finished
  236. ** or when we need to refresh in a simplerefresh window.
  237. ** Note: You may only render within the rectangle
  238. **       _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj).
  239. *)
  240.  
  241. (*/// "mDraw(cl : id.IClassPtr; obj : id.ObjectPtr; msg : mc.mpDraw) : ADDRES" *)
  242.  
  243. PROCEDURE mDraw(cl : id.IClassPtr; obj : id.ObjectPtr; msg : mc.mpDrawPtr) : ADDRESS;
  244.  
  245. VAR
  246.   data : POINTER TO Data ;
  247.   i    : INTEGER ;
  248.  
  249. BEGIN
  250.   data := mc.InstData(cl, obj) ;
  251.  
  252.   (*
  253.   ** let our superclass draw itself first, area class would
  254.   ** e.g. draw the frame and clear the whole region. What
  255.   ** it does exactly depends on msg->flags.
  256.   *)
  257.  
  258.   IF DoSuperMethodA(cl, obj, msg) # NIL THEN END ;
  259.  
  260.   (*
  261.   ** if MADF_DRAWOBJECT isn't set, we shouldn't draw anything.
  262.   ** MUI just wanted to update the frame or something like that.
  263.   *)
  264.  
  265.   IF NOT (mc.drawObject IN msg^.flags) THEN RETURN NIL END ;
  266.  
  267.   (*
  268.   ** test if someone changed our pen
  269.   *)
  270.  
  271.   IF data^.penchange THEN
  272.     data^.penchange := FALSE ;
  273.     ml.moReleasePen(mc.muiRenderInfo(obj), data^.pen) ;
  274.     data^.pen := ml.moObtainPen(mc.muiRenderInfo(obj), ADR(data^.penspec)) ;
  275.   END (* IF *) ;
  276.  
  277.   (*
  278.   ** ok, everything ready to render...
  279.   ** Note that we *must* use the MUIPEN() macro before actually
  280.   ** using pens from MUI_ObtainPen() in rendering calls.
  281.   *)
  282.  
  283.   gl.SetAPen(mc.OBJ_rp(obj),mc.muiPen(data^.pen));
  284.  
  285.   FOR i := mc.OBJ_mleft(obj) TO mc.OBJ_mright(obj) BY 5 DO
  286.     gl.Move(mc.OBJ_rp(obj),mc.OBJ_mleft(obj),mc.OBJ_mtop(obj));
  287.     gl.Draw(mc.OBJ_rp(obj),i,mc.OBJ_mbottom(obj));
  288.     gl.Move(mc.OBJ_rp(obj),mc.OBJ_mright(obj),mc.OBJ_mtop(obj));
  289.     gl.Draw(mc.OBJ_rp(obj),i,mc.OBJ_mbottom(obj));
  290.   END (* FOR *) ;
  291.  
  292.   RETURN NIL ;
  293. END mDraw ;
  294.  
  295. (*\\\*)
  296.  
  297. (*
  298. ** Here comes the dispatcher for our custom class. We only need to
  299. ** care about MUIM_AskMinMax and MUIM_Draw in this simple case.
  300. ** Unknown/unused methods are passed to the superclass immediately.
  301. *)
  302.  
  303. (*/// "MyDispatcher(cl : id.IClassPtr; obj : ADDRESS; msg : ADDRESS) : ADDRESS" *)
  304.  
  305. PROCEDURE MyDispatcher(cl : id.IClassPtr; obj : ADDRESS; msg : ADDRESS) : ADDRESS ;
  306.  
  307. VAR
  308.   mid : LONGCARD ;
  309.  
  310. BEGIN
  311.   mid := CAST(id.Msg, msg)^.methodID ;
  312.  
  313.      IF mid = id.omNEW      THEN RETURN mNew(cl, obj, msg)
  314.   ELSIF mid = id.omDISPOSE  THEN RETURN mDispose(cl, obj, msg)
  315.   ELSIF mid = id.omSET      THEN RETURN mSet(cl, obj, msg)
  316.   ELSIF mid = id.omGET      THEN RETURN mGet(cl, obj, msg)
  317.   ELSIF mid = m.mmAskMinMax THEN RETURN mAskMinMax(cl, obj, msg)
  318.   ELSIF mid = m.mmSetup     THEN RETURN mSetup(cl, obj, msg)
  319.   ELSIF mid = m.mmCleanup   THEN RETURN mCleanup(cl, obj, msg)
  320.   ELSIF mid = m.mmDraw      THEN RETURN mDraw(cl, obj, msg)
  321.   ELSE
  322.     RETURN DoSuperMethodA(cl, obj, msg)
  323.   END (* CASE *) ;
  324. END MyDispatcher ;
  325.  
  326. (*\\\*)
  327.  
  328. (***************************************************************************)
  329. (* Thats all there is about it. Now lets see how things are used...        *)
  330. (***************************************************************************)
  331.  
  332. VAR
  333.   app,
  334.   window,
  335.   grp,
  336.   myObj,
  337.   pen      : id.ObjectPtr ;
  338.   mcc      : mc.mCustomClassPtr ;
  339.   signals  : LONGSET ;
  340.   startpen : m.mPenSpecPtr ;
  341.   NULL     :=ADDRESS{NIL};
  342.  
  343.   tags     : ARRAY [0..31] OF LONGINT ;
  344.   tags1    : ARRAY [0..9]  OF LONGINT ;
  345.  
  346. BEGIN
  347.   (* Create the new custom class with a call to MUI_CreateCustomClass(). *)
  348.   (* Caution: This function returns not a struct IClass, but a           *)
  349.   (* struct MUI_CustomClass which contains a struct IClass to be         *)
  350.   (* used with NewObject() calls.                                        *)
  351.   (* Note well: MUI creates the dispatcher hook for you, you may         *)
  352.   (* *not* use its h_Data field! If you need custom data, use the        *)
  353.   (* cl_UserData of the IClass structure!                                *)
  354.  
  355.   IF ml.muiMasterVersion < 12 THEN ms.fail(NULL, "You need MUI 3.1 to run this demo.") END;
  356.  
  357.   IF NOT mcs.InitClass(mcc, NIL, ADR(m.mcArea), NIL, SIZE(Data), MyDispatcher) THEN
  358.     ms.fail(NULL, "Could not create custom class.")
  359.   END (* IF *) ;
  360.  
  361.   pen := mm.PoppenObject(TAG(tags, m.maCycleChain, TRUE,
  362.                                    m.maWindowTitle, ADR("Custom Class Color"),
  363.                              ud.tagDone)) ;
  364.  
  365.   myObj := il.NewObjectA(mcc^.class, NIL, TAG(tags, m.maFrame,      m.mvFrameText,
  366.                                                     m.maBackground, m.miBACKGROUND,
  367.                                               ud.tagDone)) ;
  368.  
  369.   grp := mm.GroupObject(TAG(tags, m.maGroupHoriz,  FALSE,
  370.                                   mm.Child,        mm.TextObject(TAG(tags1, m.maFrame, m.mvFrameText,
  371.                                                                             m.maBackground, m.miTextBack,
  372.                                                                             m.maTextContents, ADR("\ecThis is a custom class with attributes.\nClick on the button at the bottom of\nthe window to adjust the color."),
  373.                                                                      ud.tagDone)),
  374.                                   mm.Child,        myObj,
  375.                                   mm.Child,        mm.GroupObject(TAG(tags1, m.maWeight, 10,
  376.                                                                              m.maGroupHoriz, TRUE,
  377.                                                                              mm.Child, mm.FreeLabel(ADR("Custom Class Color:")),
  378.                                                                              mm.Child, pen,
  379.                                                                       ud.tagDone)),
  380.  
  381.                             ud.tagDone)) ;
  382.  
  383.   window := mm.WindowObject(TAG(tags, m.maWindowTitle, ADR("Another Custom Class"),
  384.                                       m.maWindowID,    mm.MakeID("CLS2"),
  385.                                       mm.WindowContents, grp,
  386.                                 ud.tagDone)) ;
  387.  
  388.   app := mm.ApplicationObject(TAG(tags, m.maApplicationTitle,       ADR("Class2-M2"),
  389.                                         m.maApplicationVersion,     ADR("$VER: Class2-M2 11.1 (21.9.95)"),
  390.                                         m.maApplicationCopyright,   ADR("©1995, Olaf Peters, Stefan Stuntz"),
  391.                                         m.maApplicationAuthor,      ADR("Olaf Peters, Stefan Stuntz"),
  392.                                         m.maApplicationDescription, ADR("Demonstrate the use of custom classes."),
  393.                                         m.maApplicationBase,        ADR("CLASS2M2"),
  394.                                         mm.SubWindow,               window,
  395.                                   ud.tagDone)) ;
  396.  
  397.   IF app = NIL THEN ms.fail(NULL, "Failed to create Application.") END ;
  398.  
  399.   mm.NoteClose(app, window, m.mvApplicationReturnIDQuit) ;
  400.  
  401.   ms.DoMethod(pen,TAG(tags, m.mmNotify, m.maPendisplaySpec, m.mvEveryTime,
  402.                          myObj, 3, m.mmSet, MyAttrPen, m.mvTriggerValue,
  403.                    ud.tagDone));
  404.  
  405.   mm.get(pen, m.maPendisplaySpec, ADR(startpen)) ;
  406.   mm.set(myObj, MyAttrPen, LONGCARD(startpen)) ;
  407.  
  408. (*
  409. ** Input loop...
  410. *)
  411.  
  412.   mm.set(window, m.maWindowOpen, LONGCARD(TRUE)) ;
  413.  
  414.   signals := LONGSET{} ;
  415.  
  416.   LOOP
  417.     IF ms.DOMethod(app, TAG(tags, m.mmApplicationNewInput, ADR(signals))) = m.mvApplicationReturnIDQuit THEN EXIT END ;
  418.  
  419.     IF signals # LONGSET{} THEN
  420.       INCL(signals, ctrlC) ;
  421.       signals := Wait(signals) ;
  422.       IF ctrlC IN signals THEN EXIT END ;
  423.     END (* IF *) ;
  424.   END (* WHILE *) ;
  425.  
  426.   mm.set(window, m.maWindowOpen, LONGCARD(FALSE)) ;
  427.  
  428. (*
  429. ** Shut down...
  430. *)
  431.  
  432. CLOSE
  433.   IF app # NIL THEN
  434.     ml.mDisposeObject(app) ;
  435.     app := NIL ;
  436.   END (* IF *) ;
  437.  
  438.   mcs.RemoveClass(mcc) ;
  439. END Class2.
  440.